useInsertionEffect
🧑🏻💻 useInsertionEffect
useInsertionEffect
는useEffect
의 버전 중 하나로, DOM 변이 전에 실행된다. (DOM
변이 전에 스타일을 주입한다.)
✅ useInsertionEffect 문법
useInsertionEffect(setup, dependencies?)
setup
는 Effect의 로직이 포함된 함수이다. 셋업 함수는 클린업 함수를 선택적으로 반환할 수도 있다.dependencies
는setup
코드 내에서 참조된 모든 반응형 값의 목록이다. 반응형 값에는 props, state, 컴포넌트 본문 내부에서 직접 선언된 모든 변수와 함수가 포함된다.undefined
를 반환한다.
🧑🏻💻 알고 가기
✅ 주의 사항
useInsertionEffect
는 CSS-in-JS 라이브러리 작성자를 위한 훅이다.CSS-in-JS 라이브러리에서 작업 중, 런타임에
<style>
태그를 주입하는 경우가 아니라면,useEffect
나useLayoutEffect
가 더 나을 수 있다.Effect는 클라이언트에서만 실행된다. 서버 렌더링 중에는 실행되지 않는다. (
useEffect
와 마찬가지로useInsertionEffect
는 서버에서 실행되지 않는다.)useInsertionEffect
가 실행될 때까지는 DOM이 아직 업데이트되지 않은 상태이기 때문에 refs가 아직 첨부되지 않은 상태이다.useInsertionEffect
내부에서는 state를 업데이트할 수 없다.
🧑🏻💻 활용 및 생각할 거리
✅ useInsertionEffect를 사용하는 경우
// Inside your CSS-in-JS library
// CSS-in-JS 라이브러리 코드 내부에
let isInserted = new Set();
function useCSS(rule) {
useInsertionEffect(() => {
// As explained earlier, we don't recommend runtime injection of <style> tags.
// 앞서 설명한 것처럼 <style> 태그의 런타임 주입은 권장하지 않습니다.
// But if you have to do it, then it's important to do in useInsertionEffect.
// 하지만 런타임 주입을 해야한다면, useInsertionEffect에서 수행하는 것이 중요합니다.
if (!isInserted.has(rule)) {
isInserted.add(rule);
document.head.appendChild(getStyleForRule(rule));
}
});
return rule;
}
function Button() {
const className = useCSS('...');
return <div className={className} />;
}
- 런타임 주입이 React 라이프 사이클에서 잘못된 시점이 발생할 때
- DOM 변경 전에 스타일을 주입할 때
✅ CSS-in-JS 라이브러리에서 동적 스타일 삽입하기
- 3가지 접근 방식
- 컴파일러를 사용하여 CSS 파일로 정적 추출
- 인라인 스타일. ex)
<div style={{ opacity: 1 }}>
- 런타임에
<style>
태그 삽입
✅ 런타임 환경에서 <style>
태그 주입을 권장하지 않는 이유
- 브라우저에서 스타일을 훨씬 더 자주 다시 계산하도록 하기 때문이다.
- 런타임 주입이 React 라이프 사이클에서 잘못된 시점에 발생하면 속도가 매우 느려질 수 있다.
- 2번의 경우
useInsertionEffect
를 활용하여 해결 가능하지만 React에서는 가급적 아래 방식들을 더 권장한다.
- 컴파일러를 사용하여 CSS 파일로 정적 추출하기.
- 인라인 스타일 사용하기.
- 예:
<div style={{ opacity: 1 }}>
- 예: